home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
ada
/
gnat1792.zip
/
gnat179b
/
t-adainc
/
s-tasren.adb
< prev
next >
Wrap
Text File
|
1994-05-19
|
54KB
|
1,596 lines
-----------------------------------------------------------------------------
-- --
-- GNU ADA RUNTIME LIBRARY (GNARL) COMPONENTS --
-- --
-- S Y S T E M . T A S K I N G . R E N D E Z V O U S --
-- --
-- B o d y --
-- --
-- $Revision: 1.9 $ --
-- --
-- Copyright (c) 1991,1992,1993, FSU, All Rights Reserved --
-- --
-- GNARL is free software; you can redistribute it and/or modify it under --
-- terms of the GNU Library General Public License as published by the --
-- Free Software Foundation; either version 2, or (at your option) any --
-- later version. GNARL is distributed in the hope that it will be use- --
-- ful, but but WITHOUT ANY WARRANTY; without even the implied warranty of --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Gen- --
-- eral Library Public License for more details. You should have received --
-- a copy of the GNU Library General Public License along with GNARL; see --
-- file COPYING. If not, write to the Free Software Foundation, 675 Mass --
-- Ave, Cambridge, MA 02139, USA. --
-- --
-----------------------------------------------------------------------------
with System.Task_Primitives; use System.Task_Primitives;
with System.Tasking.Abortion;
-- Used for Abortion.Defer_Abortion,
-- Abortion.Undefer_Abortion
-- Abortion.Abort_To_Level
with System.Tasking.Protected_Objects;
-- Used for Protected_Objects.Check_Exception
with System.Error_Reporting;
-- Used for Error_Reporting.Assert
-- with System.Tasking.Queuing; use System.Tasking.Queuing;
-- Temporary. (queuing is in Tasking)
with System.Tasking.Runtime_Types;
-- Used for Runtime_Types.ATCB_Ptr,
-- Runtime_Types.ATCB_To_ID,
-- Runtime_Types.ID_To_ATCB,
-- Runtime_Types.Null_PO;
-- Runtime_Types."<",
-- Runtime_Types.">=",
-- Runtime_Types."=",
-- Runtime_Types.Task_Stage
-- Runtime_Types.Accepting_State
-- Runtime_Types.Vulnerable_Complete_Activation
with System.Compiler_Exceptions;
-- Used for Compiler_Exceptions."="
package body System.Tasking.Rendezvous is
function ID_To_ATCB (ID : Task_ID) return Runtime_Types.ATCB_Ptr
renames Tasking.Runtime_Types.ID_To_ATCB;
function ATCB_To_ID (Ptr : Runtime_Types.ATCB_Ptr) return Task_ID
renames Runtime_Types.ATCB_To_ID;
procedure Assert (B : Boolean; M : String)
renames Error_Reporting.Assert;
procedure Defer_Abortion
renames Abortion.Defer_Abortion;
procedure Undefer_Abortion renames
Abortion.Undefer_Abortion;
-- Following should be replaced by use type ???
function "<" (L, R : Runtime_Types.Task_Stage) return Boolean
renames Runtime_Types."<";
function ">=" (L, R : Runtime_Types.Task_Stage) return Boolean
renames Runtime_Types.">=";
function "=" (L, R : Runtime_Types.Accepting_State) return Boolean
renames Runtime_Types."=";
function "=" (L, R : Exception_ID)
return Boolean renames Compiler_Exceptions."=";
type Select_Treatment is (
Accept_Alternative_Selected,
Else_Selected,
Terminate_Selected,
Accept_Alternative_Open,
No_Alternative_Open);
Default_Treatment : constant array (Select_Modes) of Select_Treatment :=
(Simple_Mode => No_Alternative_Open,
Else_Mode => Else_Selected,
Terminate_Mode => Terminate_Selected);
-----------------------
-- Local Subprograms --
-----------------------
procedure Make_Passive
(T : Runtime_Types.ATCB_Ptr);
-- Record that task T is passive.
procedure Boost_Priority
(Call : Entry_Call_Link;
Acceptor : Runtime_Types.ATCB_Ptr);
pragma Inline (Boost_Priority);
procedure Test_Call
(Entry_Call : in out Entry_Call_Link;
Rendezvous_Completed : out Boolean);
-- Test if a rendezvous can be made right away. Returns True if the
-- rendezvous has occurred (and finished).
-- Problem: Try not to call this when the acceptor is not accepting.
-- What does problem mean??? advice??? why??? absolute rule???
function Test_Selective_Wait
(Acceptor : Runtime_Types.ATCB_Ptr;
Open_Accepts : Accept_List_Access;
Select_Mode : Select_Modes)
return Select_Treatment;
pragma Inline (Test_Selective_Wait);
-- Test if there is a call waiting on any entry, and whether any selects
-- are open. Set Acceptor.Chosen_Index to selected alternative if an
-- accept alternative can be selected.
procedure Universal_Complete_Rendezvous (Ex : Exception_ID);
pragma Inline (Universal_Complete_Rendezvous);
-- Called by acceptor to wake up caller and optionally propagate exception
------------------
-- Make_Passive --
------------------
-- If T is the last dependent of some master in task P to become passive,
-- then release P. A special case of this is when T has no dependents
-- and is completed. In this case, T itself should be released.
-- If the parent is made passive, this is repeated recursively, with C
-- being the previous parent and P being the next parent up.
-- Note that we have to hold the locks of both P and C (locked in that
-- order) so that the Awake_Count of C and the Awaited_Dependent_Count of
-- P will be synchronized. Otherwise, an attempt by P to terminate can
-- preempt this routine after C's Awake_Count has been decremented to zero
-- but before C has checked the Awaited_Dependent_Count of P. P would not
-- count C in its Awaited_Dependent_Count since it is not awake, but it
-- might count other awake dependents. When C gained control again, it
-- would decrement P's Awaited_Dependent_Count to indicate that it is
-- passive, even though it was never counted as active. This would cause
-- P to wake up before all of its dependents are passive.
-- Note : Any task with an interrupt entry should never become passive.
-- Support for this feature needs to be added here.
procedure Make_Passive (T : Runtime_Types.ATCB_Ptr) is
P : Runtime_Types.ATCB_Ptr;
-- Task whose Awaited_Dependent_Count may be decremented.
C : Runtime_Types.ATCB_Ptr;
-- Task whose awake-count gets decremented.
H : Runtime_Types.ATCB_Ptr;
-- Highest task that is ready to terminate dependents.
Taken : Boolean;
Activator : Runtime_Types.ATCB_Ptr;
begin
Runtime_Types.Vulnerable_Complete_Activation (T);
Write_Lock (T.L);
if T.Stage >= Runtime_Types.Passive then
Unlock (T.L);
return;
else
T.Stage := Runtime_Types.Passive;
Unlock (T.L);
end if;
H := null;
P := T.Parent;
C := T;
while C /= null loop
if P /= null then
Write_Lock (P.L);
Write_Lock (C.L);
C.Awake_Count := C.Awake_Count - 1;
if C.Awake_Count /= 0 then
-- C is not passive; we cannot make anything above this point
-- passive.
Unlock (C.L);
Unlock (P.L);
exit;
end if;
if P.Awaited_Dependent_Count /= 0 then
-- We have hit a non-task master; we will not be able to make
-- anything above this point passive.
P.Awake_Count := P.Awake_Count - 1;
if C.Mast